#include "Object.hpp"

namespace Pdf
{
    Object::Object()
        : type(ObjectType_Null)
    {
    }

    Object::Object(ObjectRange const & objectRange, ObjectType objectType)
        : type(objectType)
    {
        switch (objectType)
        {
        case ObjectType_Array:
            valueArray = objectRange;
            break;
        case ObjectType_Dictionary:
            valueDictionary = objectRange;
            break;
        default:
            throw 0; // TODO: rise error
        }
    }

    Object::Object(unsigned int identifier, unsigned int generation)
        : type(ObjectType_Indirect)
    {
        valueIndirect.identifier = identifier;
        valueIndirect.generation = generation;
    }

    Object::Object(bool value)
        : type(ObjectType_Boolean)
        , valueBoolean(value)
    {
    }

    Object::Object(int value)
        : type(ObjectType_Integer)
        , valueInteger(value)
    {
    }

    Object::Object(double value)
        : type(ObjectType_Real)
        , valueReal(value)
    {
    }

    Object::Object(StringValue const & value)
        : type(ObjectType_String)
    {
        valueString = value;
    }

    Object::Object(NameNode const * value)
        : type(ObjectType_Name)
        , valueName(value)
    {
    }

    Object::Object(Stream const * value)
        : type(ObjectType_Stream)
        , valueStream(value)
    {
    }

    ObjectType Object::getType() const
    {
        return type;
    }

    bool Object::getBoolean() const
    {
        switch (type)
        {
        case ObjectType_Boolean:
            return valueBoolean;
        default:
            throw 0; // TODO: rise error
        }
    }

    int Object::getInteger() const
    {
        switch (type)
        {
        case ObjectType_Integer:
            return valueInteger;
        default:
            throw 0; // TODO: rise error
        }
    }

    double Object::getReal() const
    {
        switch (type)
        {
        case ObjectType_Integer:
            return static_cast<double>(valueInteger);
        case ObjectType_Real:
            return valueReal;
        default:
            throw 0; // TODO: rise error
        }
    }

    StringValue const & Object::getString() const
    {
        switch (type)
        {
        case ObjectType_String:
            return valueString;
        default:
            throw 0; // TODO: rise error
        }
    }

    NameNode const * Object::getName() const
    {
        switch (type)
        {
        case ObjectType_Name:
            return valueName;
        default:
            throw 0; // TODO: rise error
        }
    }

    ObjectRange const & Object::getArray() const
    {
        switch (type)
        {
        case ObjectType_Array:
            return valueArray;
        default:
            throw 0; // TODO: rise error
        }
    }

    ObjectRange const & Object::getDictionary() const
    {
        switch (type)
        {
        case ObjectType_Dictionary:
            return valueDictionary;
        default:
            throw 0; // TODO: rise error
        }
    }

    Stream const * Object::getStream() const
    {
        switch (type)
        {
        case ObjectType_Stream:
            return valueStream;
        default:
            throw 0; // TODO: rise error
        }
    }

    ObjectReference const & Object::getIndirect() const
    {
        switch (type)
        {
        case ObjectType_Indirect:
            return valueIndirect;
        default:
            throw 0; // TODO: rise error
        }
    }
}